package com.biye.auth.service.impl;

import com.alipay.api.AlipayApiException;
import com.base.common.alipay.util.AlipayUtil;
import com.base.common.edu.entity.StuAccount;
import com.base.common.edu.entity.StuAccountLog;
import com.base.common.edu.entity.Student;
import com.base.common.edu.mapper.StuAccountLogMapper;
import com.base.common.edu.mapper.StuAccountMapper;
import com.base.common.edu.mapper.StudentMapper;
import com.base.common.edu.util.Dateutil;
import com.biye.auth.service.MoneyCallBackService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Map;

@Service
@Transactional
public class MoneyCallBackServiceImpl implements MoneyCallBackService {

    @Resource
    private StuAccountMapper stuAccountMapper;

    @Resource
    private StuAccountLogMapper stuAccountLogMapper;

    @Resource
    private StudentMapper studentMapper;

    private final static Logger logger = LoggerFactory.getLogger(MoneyCallBackServiceImpl.class);

    // Top up充值
    @Override
    public void updateStuAccountBalance(Map<String, String> map) {
//        JSONObject json = new JSONObject();
//        int statusCode = StatusCode.Failure._statusCode;
//        String msg = "illegal operation，banning!";

        // 拿到公用回传参数
        String passback_params = map.get("passback_params");
        // 通过@分割，[0]为uid,[1]为固定验证口令“edu”
        String identifier = passback_params.split("@")[1];

        // 不合理调用，防止用户恶意伪造支付宝异步回调进行非法充值
        if ( !"edu".equals(identifier) )
            return;

        // 判断交易状态
        String trade_status = map.get("trade_status");
        boolean trade_status_decision = trade_status.contains("SUCCESS") ? true : false;

        // 如果交易未成功也中断逻辑
        if ( !trade_status_decision )
            return;

        String buyer_pay_amount = map.get("buyer_pay_amount");
        String u_id = passback_params.split("@")[0];

        StuAccount stuAccount = stuAccountMapper.queryStuAccountById(u_id);
        // 若该学生账号下未初始化余额账户，首先初始化账户
        if ( stuAccount == null ){

            Student student = studentMapper.queryStudentById(u_id);
            if( student != null) {
                /***
                 * 如果学生账号存在，那么需要帮该学生初始化账户
                 */
                StuAccount init_stuAccount = new StuAccount();
                init_stuAccount.setStudentAccountId(u_id);
                BigDecimal bd=new BigDecimal("0.00");
                //设置小数位数，第一个变量是小数位数，第二个变量是取舍方法(四舍五入)
                bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
                init_stuAccount.setBalance(bd);
                int i = stuAccountMapper.addStuAccount(init_stuAccount);
                System.out.println(i > 0 ? "学生ID=" + u_id + "初始化账户成功" : "学生ID=" + u_id + "初始化账户失败" );
                // 重新赋值
                stuAccount = stuAccountMapper.queryStuAccountById(u_id);
            }else{
                // 如果不存在该学生账号，那么不进行初始化账户操作
                return;
            }

        }

        if ( stuAccount != null ){

            BigDecimal balance = stuAccount.getBalance();
            balance = balance.setScale(2, BigDecimal.ROUND_HALF_UP);

            BigDecimal pay_amount =new BigDecimal(buyer_pay_amount);
            pay_amount = pay_amount.setScale(2, BigDecimal.ROUND_HALF_UP);

            // add(加)  subtract(减)  multiply(乘)   divide(除)
            BigDecimal result = balance.add(pay_amount);

            // 只有两位小数的两个数相乘，小数位也是二位，不需要setScale() again
            StuAccount init_stuAccount = new StuAccount();
            init_stuAccount.setStudentAccountId(u_id);
            init_stuAccount.setBalance(result);
            // 更新账户余额
            int i = stuAccountMapper.updateStuAccount(init_stuAccount);

            if ( i > 0 ) {
                System.out.println(i > 0 ? "学生ID=" + u_id + "账户余额更新成功" : "学生ID=" + u_id + "账户余额更新失败" );

                // 将充值记录存入Log表
                StuAccountLog stuAccountLog = new StuAccountLog();
                Student log_stu = new Student();
                log_stu.setStuID(u_id);
                stuAccountLog.setStudent(log_stu);
                stuAccountLog.setAccType(3);
                stuAccountLog.setAccExplain("学生个人账户余额充值====" + map.toString());
                stuAccountLog.setAmountPaid(pay_amount);
                stuAccountLog.setAfterSurplus(result);
                int i1 = stuAccountLogMapper.addStuAccountLog(stuAccountLog);
                System.out.println(i1 > 0 ? "学生ID=" + u_id + "账户余额更新记录插入成功" : "学生ID=" + u_id + "账户余额更新记录插入失败" );
            } else {
                // 如果系统因为某些问题，导致无法将数据持久化入数据库，则进行退款操作，退还用户充值的金额
                String out_trade_no = map.get("out_trade_no");
                String trade_no = map.get("trade_no");

                try {
                    String result__ = AlipayUtil.refund(trade_no, out_trade_no, buyer_pay_amount, "系统内部故障，暂时无法充值", Dateutil.getTimeStampString());
                    if ( result__ != null ){
                        logger.info("用户充值过程中出现错误而退款: 退款成功 {}", result__);
                    }else{
                        logger.error("用户充值过程中出现错误而退款: 退款失败 {}", "STU_ID=" + u_id + " out_trade_no=" + out_trade_no + " trade_no=" + trade_no);
                    }
                } catch (AlipayApiException e) {
                    e.printStackTrace();
                    logger.error("用户充值过程中出现错误而退款: 退款失败 {}", "STU_ID=" + u_id + " out_trade_no=" + out_trade_no + " trade_no=" + trade_no);
                }

            }

        }

    }

}
